﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MishraReader.Services
{
    [ContractClass(typeof(ITwitterApiContract))]
    public interface ITwitterApi
    {
        string CallbackUri { get; set; }
        string ConsumerKey { get; set; }
        string ConsumerKeySecret { get; set; }

        Task<Uri> GetAuthorizationUriAsync(CancellationToken cancellationToken = default(CancellationToken));

        bool IsSuccessful(Uri uri, out ITwitterAuthorization result);

        Task<ITwitterToken> TranslateAuthorizationToTokenAsync(ITwitterAuthorization authorization,
                                                               CancellationToken cancellationToken = default(CancellationToken));
    }

    [ContractClassFor(typeof(ITwitterApi))]
    internal abstract class ITwitterApiContract : ITwitterApi
    {
        public abstract string CallbackUri { get; set; }
        public abstract string ConsumerKey { get; set; }
        public abstract string ConsumerKeySecret { get; set; }


        public Task<Uri> GetAuthorizationUriAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(CallbackUri));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKey));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKeySecret));

            return null;
        }

        public bool IsSuccessful(Uri uri, out ITwitterAuthorization result)
        {
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(CallbackUri));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKey));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKeySecret));
            Contract.Requires<ArgumentNullException>(uri != null, "uri");
            Contract.Ensures((Contract.Result<bool>() && Contract.ValueAtReturn(out result) != null) ||
                            (!Contract.Result<bool>() && Contract.ValueAtReturn(out result) == null));

            result = null;
            return false;
        }

        public Task<ITwitterToken> TranslateAuthorizationToTokenAsync(ITwitterAuthorization authorization, CancellationToken cancellationToken = new CancellationToken())
        {
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(CallbackUri));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKey));
            Contract.Requires<InvalidOperationException>(!string.IsNullOrWhiteSpace(ConsumerKeySecret));
            Contract.Requires<ArgumentNullException>(authorization != null, "authorization");
            Contract.Ensures(Contract.Result<Task<ITwitterToken>>() != null);
            
            return null;
        }
    }

    [ContractClass(typeof(ITwitterAuthorizationContract))]
    public interface ITwitterAuthorization
    {
        bool IsAuthenticated { get; }
        string GetParameter(string value);
    }

    [ContractClassFor(typeof(ITwitterAuthorization))]
    internal abstract class ITwitterAuthorizationContract : ITwitterAuthorization
    {
        public abstract bool IsAuthenticated { get; }
        public string GetParameter(string value)
        {
            Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(value));
            return null;
        }
    }

    [ContractClass(typeof(ITwitterTokenContract))]
    public interface ITwitterToken
    {
        string ScreenName { get; }
        string Token { get; }
        string TokenSecret { get; }
    }

    [ContractClassFor(typeof(ITwitterToken))]
    internal abstract class ITwitterTokenContract : ITwitterToken
    {
        public string ScreenName
        {
            get
            {
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));

                return null;
            }
        }

        public string Token
        {
            get
            {
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));

                return null;
            }
        }

        public string TokenSecret
        {
            get
            {
                Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>()));

                return null;
            }
        }
    }



}